package cn.kmsoft.jssc.service.processor;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import cn.kmsoft.jssc.config.AnalyseConfig;
import cn.kmsoft.jssc.entity.analyse.*;
import cn.kmsoft.jssc.service.AnalyseTaskProcessor;
import cn.kmsoft.common.utils.StringUtil;
import cn.kmsoft.wololo.object.query.GeoJsonQuery;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;


/**
 * 土地规划的土地规划地类-空间套合叠加分析
 * 
 * @author wangq
 *
 */
public class TdghdlAnalyseTaskProcessor extends AnalyseTaskProcessor {
	private static final Logger logger = LoggerFactory.getLogger(TdghdlAnalyseTaskProcessor.class);
	//土地规划地类
	private final String analysePoint="tdghdl";//看配置文件
	private AnalyseTaskParam analyseTaskParam;
	private AnalyseConfig analyseConfig;
	
	public TdghdlAnalyseTaskProcessor(AnalyseTaskParam params, AnalyseConfig analyseConfig) {
		this.analyseTaskParam=params;
		this.analyseConfig=analyseConfig; 
	}
	
	public AnalyseTaskParam getAnalyseTaskParam() {
		return analyseTaskParam;
	}
	public void setAnalyseTaskParam(AnalyseTaskParam analyseTaskParam) {
		this.analyseTaskParam = analyseTaskParam;
	}
	
	@Override
	public TaskResult call() throws Exception {
		// TODO Auto-generated method stub
		String threadId = Thread.currentThread().getName();
		
		String tableName = this.analyseTaskParam.getTableName();
		String analyseType=this.analyseTaskParam.getAnalystType();
		String dbKey = this.analyseTaskParam.getDbKey();
		int fgeo_wkid= this.analyseTaskParam.getFgeo_wkid();
		String feaTypePoint = analyseTaskParam.getFeaTypePoint();

		AnalyseDb analyseDb = this.analyseConfig.getAnalyseDbByDbkey(dbKey);
		if(analyseDb==null){
			System.out.println();
			String errorMsg = String.format("--->TaskProcessor stop, dbKey: %s, 为null",dbKey);
			System.out.println(errorMsg);
			logger.warn(errorMsg);

			return null;
		}
		String dbType = analyseDb.getDbType();
		String dbInstance = analyseDb.getDbInstance();
		String tablespace = analyseDb.getTablespace();
		String serverId = analyseDb.getServerId();//分析服务标识

		String tableId = dbInstance + "/" + tablespace + "." + tableName;
		//注意，根据数据库类型进行分类处置。
		//若为oracle的sde，则需要添加表空间；
		if("postgresql".equalsIgnoreCase(dbType)){
			//若为postgresql的postgis库，则去掉表空间或者为postgis_33_sample.sde.dltb_2018_500155_d36
			tableId = dbInstance + "/" + dbInstance+"."+ tablespace + "." + tableName;
		}
		String operatorMethod = "intersectpy";
		if(analyseType.equalsIgnoreCase("intersect") && feaTypePoint.equalsIgnoreCase("py")){
			operatorMethod = "intersectpy";
		}else if(analyseType.equalsIgnoreCase("intersect") && feaTypePoint.equalsIgnoreCase("py2")){
			operatorMethod = "intersectpy2";
		}else if(analyseType.equalsIgnoreCase("spatialquery") && feaTypePoint.equalsIgnoreCase("py")){
			operatorMethod = "spatialQuery";
		} else if(analyseType.equalsIgnoreCase("spatialquery") && feaTypePoint.equalsIgnoreCase("py2")){
			operatorMethod = "spatialQuery2";
		} else if(analyseType.equalsIgnoreCase("difference") && feaTypePoint.equalsIgnoreCase("py")){
			operatorMethod = "difference";
		}

		AnalyseServer analyseServer = this.analyseConfig.getAnalyseServerByServerId(serverId);
		String serverUrl = analyseServer.getServerUrl();

		String targetUrl = serverUrl + "/" + operatorMethod + "/" + tableId;
		//String targetUrl = this.analyseConfig.getServerUrl() + "/" + operatorMethod + "/" + tableId;
		//String targetUrl = this.analyseConfig.getServerUrl() + "/" + analystType + "/" + tableId;

		//任务参数
		AnalyseTaskParam params = this.analyseTaskParam;
		params.setTargetUrl(targetUrl);		
		
		TaskResult taskResult = this.startAnalyse(operatorMethod,threadId, params);

		return taskResult;
	}
	
	/**
	 * start分析
	 * 
	 * TaskParam params  
	 * Return 
	 */
	@Override
	public TaskResult startAnalyse(String operatorMethod,String threadId, AnalyseTaskParam params) {
		TaskResult result = new TaskResult();
		
		String targetUrl = params.getTargetUrl();
		String jobId= params.getJobId();
		String taskId = params.getTaskId();
		String dkbh = params.getDkbh();
		GeoJsonQuery query = (GeoJsonQuery) params.getQuery();
		String tableName= params.getTableName();
		
		result.setThreadId(threadId);
		result.setJobId(jobId);
		result.setAnalystPoint(params.getAnalysePoint());
		result.setProcessorName(params.getProcessName());
		result.setTaskId(taskId);
		result.setDkbh(dkbh);
		result.setTableName(tableName);
		
		int counter=0;		
		do {
			counter++;

			System.out.println(String.format("--->doAnalyse,threadId: %s, jobId: %s, dkbh: %s, targetUrl: %s",threadId, jobId, dkbh, targetUrl));
			//叠加分析,最多3次
			List<GhdlDetailResult> ghdlDetailResultList = this.doGhdlAnalyse(jobId, targetUrl, query);
			//汇总为三级类的数据库实体对象
			Map<String, Statis03Result> ghdl03StatisResultMap = this.summaryGhdlStatis03Result(ghdlDetailResultList);

			//汇总为二级类的数据库实体对象
			List<GhtzGhdl> ghtzGhdlResults = this.convert2GhtzGhdlList(taskId, dkbh, ghdl03StatisResultMap);

			System.out.println(String.format("--->threadId: %s, jobId: %s, analysePoint: %s,叠加规划地类后获得的三级分类数量： %d", threadId,jobId,this.analysePoint,ghtzGhdlResults.size()));

			result.setSummary03Result(ghdl03StatisResultMap);
			result.setSummary03DBEntResult(ghtzGhdlResults);
			result.setDetailsListResult(ghdlDetailResultList);
			//汇总为一级类
		    GhdlSummary01Result ghdlSummary = this.summaryGhdlStatis01Result(ghdl03StatisResultMap);
		    String ghdlmcStr= ghdlSummary.getGhdlmcsStr();

		    if( !StringUtil.isNullOrEmpty(ghdlmcStr) ) {
				 result.setSummary01Result(ghdlSummary);		 
				 result.setbAnalystStatus(true);
		    }else {
		    	result.setbAnalystStatus(false);
		    }
		}
		while(result.isbAnalystStatus()==false && counter<= this.maxAnalystCount);
		
		if(result.isbAnalystStatus()==false) {
			result.setMessage("土地规划地类分析失败!");
		}

		return result;
	}
	
	/**
	 * 土地规划地类-叠加分析
	 * 
	 * @param query
	 * @return
	 */
	public List<GhdlDetailResult> doGhdlAnalyse(String jobId, String targetUrl, GeoJsonQuery query) {
		List<GhdlDetailResult> ghdlDetailResultList= new ArrayList<GhdlDetailResult>();
		
		String queryJsonStr = JSONObject.toJSONString(query);
		HttpHeaders headers = new HttpHeaders();
		headers.setContentType(MediaType.APPLICATION_JSON);
		
		HttpEntity<String> entity = new HttpEntity<>(queryJsonStr, headers);
		
		//2、转发空间分析的请求
		ResponseEntity<JSONObject> exchange = this.exchangeSpatialAnalyst(jobId, targetUrl, entity);
		JSONObject ghdlObject= exchange.getBody();
		if(ghdlObject==null || ghdlObject.getJSONArray("result")==null) {
			return ghdlDetailResultList;
		}
		
		JSONArray feasJSONArray = ghdlObject.getJSONArray("result").getJSONObject(0).getJSONArray("features");
		//List<Map<String,String>> allFeaProperties = this.parseFeaProperties(feasJSONArray);
		List<Map<String,String>> allFeaProperties = this.parseFeaGeometryAndProperties(feasJSONArray);
		int feaCount = allFeaProperties.size();		
		for(int i=0; i<feaCount;i++ ) {
			Map<String,String> feaProps = allFeaProperties.get(i);

			//将要素属性的key全部转为小写，否则oracle和postgresql数据库返回的结果会有差异
			Map<String,String> feaPropsKeyLowercCase = new HashMap<>();
			feaProps.forEach((key,value) -> feaPropsKeyLowercCase.put(key.toLowerCase(), value));

			//1-目标图层的字段值
			String bsm =feaPropsKeyLowercCase.get("bsm")!=null?feaPropsKeyLowercCase.get("bsm").toString():"-1";//BSM
			String tbbh = feaPropsKeyLowercCase.get("tbbh")!=null?feaPropsKeyLowercCase.get("tbbh").toString():"-1";//TBBH
			String ghdldm = feaPropsKeyLowercCase.get("ghdldm")!=null?feaPropsKeyLowercCase.get("ghdldm").toString():"-100";//GHDLDM
			String ghdlmc = feaPropsKeyLowercCase.get("ghdlmc")!=null?feaPropsKeyLowercCase.get("ghdlmc").toString():"未知";//GHDLMC

			//2-追加的3个几何面积
			double area = Double.parseDouble(feaPropsKeyLowercCase.get("area").toString());//叠加后重叠范围的几何面积AREA
			double fgeoarea = Double.parseDouble(feaPropsKeyLowercCase.get("fgeoarea").toString());//目标图层（sde库）原图斑几何面积FGEOAREA
			double sgeoarea = Double.parseDouble(feaPropsKeyLowercCase.get("sgeoarea").toString());//SGEOAREA

			//3-叠加相交结果的几何图形wkt
			String geomText = feaPropsKeyLowercCase.get("geom").toString();

			GhdlDetailResult ghdlResult = new GhdlDetailResult();

			ghdlResult.setFeaProps(feaProps);
			//1-目标图层的字段值
			ghdlResult.setBsm(bsm);
			ghdlResult.setTbbh(tbbh);
			ghdlResult.setGhdldm(ghdldm);
			ghdlResult.setGhdlmc(ghdlmc);
			ghdlResult.setGhdlmj(Math.abs(area));

			ghdlResult.setArea(Math.abs(area));
			ghdlResult.setFgeoarea(Math.abs(fgeoarea));//目标图层（sde库）原图斑几何面积
			ghdlResult.setSgeoarea(Math.abs(sgeoarea));//上传图斑几何面积
			ghdlResult.setGeomText(geomText);
			
			ghdlDetailResultList.add(ghdlResult);
		}
		
		return ghdlDetailResultList;
	}
	
	/**
	 * 将规划地类叠加结果转换为三级类实体对象
	 * 
	 * @param taskId  项目编号
	 * @param dkbh  地块编号
	 * @param ghdlStatis03Results  三级类详细列表
	 * @return
	 */
	private List<GhtzGhdl> convert2GhtzGhdlList(String taskId, String dkbh, Map<String,Statis03Result> ghdlStatis03Results) {
		List<GhtzGhdl> ghtzGhdlResults= new ArrayList<GhtzGhdl>();
		//规划地类代码
		Set<String> ghdldmSet = ghdlStatis03Results.keySet();
		Iterator<String> iter = ghdldmSet.iterator();
		while(iter.hasNext()) {
			String ghdldm = iter.next();
			Statis03Result ghdlStatis = ghdlStatis03Results.get(ghdldm);
			
			GhtzGhdl ghtzGhdl=new GhtzGhdl();
			ghtzGhdl.setTaskId(taskId);
			ghtzGhdl.setDkbh(dkbh);
			ghtzGhdl.setGhdldm(ghdldm);
			ghtzGhdl.setGhdlmc(ghdlStatis.getMc());
			ghtzGhdl.setGhdlmj(ghdlStatis.getAnalyseArea());
			
			ghtzGhdlResults.add(ghtzGhdl);
		}
		
		return ghtzGhdlResults;
	}
	
	public Map<String,Statis03Result>  summaryGhdlStatis03Result(List<GhdlDetailResult> ghdlDetailResultList) {
		Map<String, Statis03Result> ghdlStatisResults = new HashMap<String, Statis03Result>();

		// 汇总为三级分类统计
		Iterator<GhdlDetailResult> detailIter = ghdlDetailResultList.iterator();
		while (detailIter.hasNext()) {
			GhdlDetailResult detailResult = detailIter.next();
			String ghdldm = detailResult.getGhdldm();
			String ghdlmc = detailResult.getGhdlmc();
			Double area = detailResult.getGhdlmj();

			if (ghdlStatisResults.containsKey(ghdldm)) {
				Double areaOfSum = ghdlStatisResults.get(ghdldm).getAnalyseArea();
				ghdlStatisResults.get(ghdldm).setAnalyseArea(areaOfSum + area);
			} else {
				Statis03Result statisResult = new Statis03Result();
				statisResult.setDm(ghdldm);
				statisResult.setMc(ghdlmc);
				statisResult.setAnalyseArea(area);
				ghdlStatisResults.put(ghdldm, statisResult);
			}
		}

		return ghdlStatisResults;

	}
	
	/**
	 * 规划地类-汇总为三级类为一级二级分类
	 * @param statisResultMap
	 * @return
	 */
	private GhdlSummary01Result summaryGhdlStatis01Result(Map<String,Statis03Result> statisResultMap) {
		List<String> ghdlmcList = new ArrayList<String>();
		
		double nydAreaOfSum = 0.0;
		double gdAreaOfSum = 0.0;		
		double jsydAreaOfSum = 0.0;
		double cxjsydAreaOfSum=0.0;
		double wlydAreaOfSum = 0.0;
		
		//规划地类代码
		Set<String> ghdldmSet = statisResultMap.keySet();
		Iterator<String> iter= ghdldmSet.iterator();
		while(iter.hasNext()) {
			String ghdldm = iter.next();
			Statis03Result statisResult = statisResultMap.get(ghdldm);
			
			double area= statisResult.getAnalyseArea();
			if(this.analyseConfig.getTdlyfldmConfig().getTdghytfldm_nyd().contains(ghdldm)) {
				nydAreaOfSum= nydAreaOfSum + area;
			}			
			if( this.analyseConfig.getTdlyfldmConfig().getTdghytfldm_gd().contains(ghdldm)) {
				gdAreaOfSum= gdAreaOfSum + area;
			}			
			if( this.analyseConfig.getTdlyfldmConfig().getTdghytfldm_jsyd().contains(ghdldm)) {	
				jsydAreaOfSum= jsydAreaOfSum + area;
			}
			if( this.analyseConfig.getTdlyfldmConfig().getTdghytfldm_cxjsyd().contains(ghdldm)) {	
				cxjsydAreaOfSum= cxjsydAreaOfSum + area;
			}						
			if( this.analyseConfig.getTdlyfldmConfig().getTdghytfldm_wlyd().contains(ghdldm)) {
				wlydAreaOfSum= wlydAreaOfSum + area;
			}
			
			String ghdlmc = statisResult.getMc();
			ghdlmcList.add(ghdlmc);
		}
		
		GhdlSummary01Result ghdlSummary = new GhdlSummary01Result();
		ghdlSummary.setNydmj(nydAreaOfSum);
		ghdlSummary.setGdmj(gdAreaOfSum);
		ghdlSummary.setJsydmj(jsydAreaOfSum);
		ghdlSummary.setCxjsydmj(cxjsydAreaOfSum);
		ghdlSummary.setWlydmj(wlydAreaOfSum);
		if(ghdlmcList.size()>0) {
			ghdlSummary.setGhdlmcsStr(StringUtils.join(ghdlmcList,","));
		}else{
			ghdlSummary.setGhdlmcsStr("规划地类叠加发生异常!");
		}

		return ghdlSummary;
	}
	
}
